package com.android.devicechecker;

import java.io.IOException;
import java.util.List;

import com.android.devicechecker.interfaces.ItestActTemplate;
import com.android.util.FileOperate;
import com.android.util.enhanceToast;

import android.R.bool;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.FeatureInfo;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.Size;
import android.os.Bundle;
import android.pim.ICalendar.Parameter;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.RelativeLayout;

// ----------------------------------------------------------------------

public class testCameraActivity extends ItestActTemplate {
	private Preview mPreview;
	Camera mCamera;
	int numberOfCameras;
	int cameraCurrentlyLocked;
	private enhanceToast mEnhanceToast;

	private static final int ID_BTN_OK_CAMERA = 1;
	private static final int ID_BTN_CANCEL_CAMERA = 2;
	private Button btn_ok;
	private Button btn_cancel;

	// The first rear facing camera
	int defaultCameraId;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		// Hide the window title.
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

		// Create a RelativeLayout container that will hold a SurfaceView,
		// and set it as the content of our activity.

		/* Create button and setting */
		btn_ok = new Button(this);
		btn_ok.setText(R.string.btn_ok_text);
		btn_ok.setId(ID_BTN_OK_CAMERA);
		setYesBtnOnClickListener(btn_ok, FileOperate.TestItemCamera);
		btn_cancel = new Button(this);
		btn_cancel.setText(R.string.btn_cancel_text);
		btn_cancel.setId(ID_BTN_CANCEL_CAMERA);
		setNoBtnOnClickListener(btn_cancel, FileOperate.TestItemCamera);

		/* main layout */
		RelativeLayout layout = new RelativeLayout(this);
		mPreview = new Preview(this);
		layout.addView(mPreview, new RelativeLayout.LayoutParams(
				LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));

		/* button layout */
		RelativeLayout btn_layout = new RelativeLayout(this);
		RelativeLayout.LayoutParams btn_layout_param = new RelativeLayout.LayoutParams(
				LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
		btn_layout.setLayoutParams(btn_layout_param);

		/* ok button */
		RelativeLayout.LayoutParams btn_ok_param = new RelativeLayout.LayoutParams(
				(int) getResources().getDimension(
						R.dimen.test_item_bottom_button_width),
				(int) getResources().getDimension(
						R.dimen.test_item_bottom_button_heith));
		btn_ok_param.addRule(RelativeLayout.ALIGN_PARENT_RIGHT,
				RelativeLayout.TRUE);
		btn_layout.addView(btn_ok, btn_ok_param);

		/* cancel button */
		RelativeLayout.LayoutParams btn_cancel_param = new RelativeLayout.LayoutParams(
				(int) getResources().getDimension(
						R.dimen.test_item_bottom_button_width),
				(int) getResources().getDimension(
						R.dimen.test_item_bottom_button_heith));
		btn_cancel_param
				.addRule(RelativeLayout.ALIGN_TOP, ID_BTN_CANCEL_CAMERA);
		btn_cancel_param.addRule(RelativeLayout.LEFT_OF, ID_BTN_CANCEL_CAMERA);
		btn_layout.addView(btn_cancel, btn_cancel_param);

		/* sub layout */
		RelativeLayout.LayoutParams layout_param = new RelativeLayout.LayoutParams(
				LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
		layout_param.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM,
				RelativeLayout.TRUE);
		layout.addView(btn_layout, layout_param);

		/* set custom view */
		setContentView(layout);

		mEnhanceToast = new enhanceToast(this);
		mEnhanceToast.displayToast(getString(R.string.test_camera_tips));

		// Find the total number of cameras available
		numberOfCameras = Camera.getNumberOfCameras();

		// Find the ID of the default camera
		CameraInfo cameraInfo = new CameraInfo();
		for (int i = 0; i < numberOfCameras; i++) {
			Camera.getCameraInfo(i, cameraInfo);
			if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
				defaultCameraId = i;
			}
		}
	}

	@Override
	protected void onResume() {
		super.onResume();

		// Open the default i.e. the first rear facing camera.
		mCamera = Camera.open();
		cameraCurrentlyLocked = defaultCameraId;
		mPreview.setCamera(mCamera);
	}

	@Override
	protected void onPause() {
		super.onPause();

		// Because the Camera object is a shared resource, it's very
		// important to release it when the activity is paused.
		if (mCamera != null) {
			mPreview.setCamera(null);
			mCamera.release();
			mCamera = null;
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {

		// Inflate our menu which can gather user input for switching camera
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.camera_menu, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle item selection
		switch (item.getItemId()) {
		case R.id.switch_cam:
			// check for availability of multiple cameras
			if (numberOfCameras == 1) {
				AlertDialog.Builder builder = new AlertDialog.Builder(this);
				builder.setMessage(this.getString(R.string.camera_alert))
						.setNeutralButton("Close", null);
				AlertDialog alert = builder.create();
				alert.show();
				return true;
			}

			// OK, we have multiple cameras.
			// Release this camera -> cameraCurrentlyLocked
			if (mCamera != null) {
				Parameters parameters = mCamera.getParameters();
				parameters.setFlashMode(Parameters.FLASH_MODE_OFF);
				mCamera.setParameters(parameters);
				mCamera.stopPreview();

				mPreview.setCamera(null);
				mCamera.release();
				mCamera = null;
			}

			// Acquire the next camera and request Preview to reconfigure
			// parameters.
			int cameraIdCurrent = (cameraCurrentlyLocked + 1) % numberOfCameras;
			mCamera = Camera.open(cameraIdCurrent);
			cameraCurrentlyLocked = (cameraCurrentlyLocked + 1)
					% numberOfCameras;

			CameraInfo cameraInfo = new CameraInfo();

			Camera.getCameraInfo(cameraIdCurrent, cameraInfo);
			if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK
					&& haveFlashLight()) {
				Parameters parameters = mCamera.getParameters();
				parameters.setFlashMode(Camera.Parameters.FLASH_MODE_ON);
				parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
				mCamera.setParameters(parameters);
			}

			mPreview.switchCamera(mCamera);

			// Start the preview
			mCamera.startPreview();
			return true;
		default:
			return super.onOptionsItemSelected(item);
		}
	}

	// 以下代码判断手机是否带闪光灯
	public boolean haveFlashLight() {
		FeatureInfo[] feature = getApplicationContext().getPackageManager()
				.getSystemAvailableFeatures();
		for (FeatureInfo featureInfo : feature) {
			if (PackageManager.FEATURE_CAMERA_FLASH.equals(featureInfo.name)) {
				return true;
			}
		}
		return false;
	}

	// ----------------------------------------------------------------------

	/**
	 * A simple wrapper around a Camera and a SurfaceView that renders a
	 * centered preview of the Camera to the surface. We need to center the
	 * SurfaceView because not all devices have cameras that support preview
	 * sizes at the same aspect ratio as the device's display.
	 */
	class Preview extends ViewGroup implements SurfaceHolder.Callback {
		private final String TAG = "Preview";

		SurfaceView mSurfaceView;
		SurfaceHolder mHolder;
		Size mPreviewSize;
		List<Size> mSupportedPreviewSizes;
		Camera mCamera;
		Context mContext;

		Preview(Context context) {
			super(context);

			mContext = context;
			mSurfaceView = new SurfaceView(context);
			addView(mSurfaceView);

			// Install a SurfaceHolder.Callback so we get notified when the
			// underlying surface is created and destroyed.
			mHolder = mSurfaceView.getHolder();
			mHolder.addCallback(this);
			mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
		}

		public void setCamera(Camera camera) {
			mCamera = camera;
			if (mCamera != null) {
				mSupportedPreviewSizes = mCamera.getParameters()
						.getSupportedPreviewSizes();
				requestLayout();
			}
		}

		public void switchCamera(Camera camera) {
			setCamera(camera);
			try {
				camera.setPreviewDisplay(mHolder);
			} catch (IOException exception) {
				Log.e(TAG, "IOException caused by setPreviewDisplay()",
						exception);
			}
			Camera.Parameters parameters = camera.getParameters();
			parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
			requestLayout();
			camera.setParameters(parameters);
		}

		@Override
		protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
			// We purposely disregard child measurements because act as a
			// wrapper to a SurfaceView that centers the camera preview instead
			// of stretching it.
			final int width = resolveSize(getSuggestedMinimumWidth(),
					widthMeasureSpec);
			final int height = resolveSize(getSuggestedMinimumHeight(),
					heightMeasureSpec);
			setMeasuredDimension(width, height);

			if (mSupportedPreviewSizes != null) {
				mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes,
						width, height);
			}
		}

		@Override
		protected void onLayout(boolean changed, int l, int t, int r, int b) {
			if (changed && getChildCount() > 0) {
				final View child = getChildAt(0);

				final int width = r - l;
				final int height = b - t;

				int previewWidth = width;
				int previewHeight = height;
				if (mPreviewSize != null) {
					previewWidth = mPreviewSize.width;
					previewHeight = mPreviewSize.height;
				}

				// Center the child SurfaceView within the parent.
				if (width * previewHeight > height * previewWidth) {
					final int scaledChildWidth = previewWidth * height
							/ previewHeight;
					child.layout((width - scaledChildWidth) / 2, 0,
							(width + scaledChildWidth) / 2, height);
				} else {
					final int scaledChildHeight = previewHeight * width
							/ previewWidth;
					child.layout(0, (height - scaledChildHeight) / 2, width,
							(height + scaledChildHeight) / 2);
				}
			}
		}

		public void surfaceCreated(SurfaceHolder holder) {
			// The Surface has been created, acquire the camera and tell it
			// where
			// to draw.
			try {
				if (mCamera != null) {
					mCamera.setPreviewDisplay(holder);
				}
			} catch (IOException exception) {
				Log.e(TAG, "IOException caused by setPreviewDisplay()",
						exception);
			}
		}

		public void surfaceDestroyed(SurfaceHolder holder) {
			// Surface will be destroyed when we return, so stop the preview.
			if (mCamera != null) {
				mCamera.stopPreview();
			}
		}

		private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
			final double ASPECT_TOLERANCE = 0.1;
			double targetRatio = (double) w / h;
			if (sizes == null)
				return null;

			Size optimalSize = null;
			double minDiff = Double.MAX_VALUE;

			int targetHeight = h;

			// Try to find an size match aspect ratio and size
			for (Size size : sizes) {
				double ratio = (double) size.width / size.height;
				if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
					continue;
				if (Math.abs(size.height - targetHeight) < minDiff) {
					optimalSize = size;
					minDiff = Math.abs(size.height - targetHeight);
				}
			}

			// Cannot find the one match the aspect ratio, ignore the
			// requirement
			if (optimalSize == null) {
				minDiff = Double.MAX_VALUE;
				for (Size size : sizes) {
					if (Math.abs(size.height - targetHeight) < minDiff) {
						optimalSize = size;
						minDiff = Math.abs(size.height - targetHeight);
					}
				}
			}
			return optimalSize;
		}

		public void surfaceChanged(SurfaceHolder holder, int format, int w,
				int h) {
			// Now that the size is known, set up the camera parameters and
			// begin
			// the preview.
			Camera.Parameters parameters = mCamera.getParameters();
			parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
			requestLayout();

			if (((testCameraActivity) mContext).haveFlashLight()) {
				parameters.setFlashMode(Camera.Parameters.FLASH_MODE_ON);
				parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
			}

			mCamera.setParameters(parameters);
			mCamera.startPreview();
		}

	}
}
